/*
 * Copyright 2008-2009 Aying.Net with Fuchun.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.aying.html;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import net.aying.resources.Resources;
import net.aying.util.StringUtils;

/**
 * 包含基本 <code>HTML</code> 操作的常用方法的便捷工具类。
 * 
 * @author Fuchun
 * @version 1.0, 2009-6-9
 */
public class HtmlUtils extends StringUtils {
    
    @SuppressWarnings("unused")
    private static final Log log = LogFactory.getLog(HtmlUtils.class);

    /** 用于保存查找HTML标签的正则表达式的缓存。 */
    private static Map<String, String> tagRegexCaches = Collections
            .synchronizedMap(new HashMap<String, String>());

    /** 用于保存查找HTML标签属性的正则表达式的缓存。 */
    private static Map<String, String> attrRegexCaches = Collections
            .synchronizedMap(new HashMap<String, String>());

    /**
     * 获取用于查找给定标签(非对称标签)名称的 <code>HTML</code> 元素标签的正则表达式。
     * 
     * @param tagName 给定的标签名称(忽略大小写)。
     * @return 查找标签的正则表达式。
     * @throws IllegalArgumentException 若指定的标签名称 <tt>tagName</tt> 为 <code>NULL</code>
     * 或空字符串时，抛出此异常。
     * @see #getTagRegex(String, boolean)
     */
    public static String getTagRegex(String tagName) {
        return getTagRegex(tagName, false);
    }
    
    /**
     * 获取用于查找给定标签名称的 <code>HTML</code> 元素标签的正则表达式。
     * 
     * @param tagName 给定的标签名称(忽略大小写)。
     * @param hasEndTag 是否有关闭标签。
     * @return 查找标签的正则表达式。
     * @throws IllegalArgumentException 若指定的标签名称 <tt>tagName</tt> 为 <code>NULL</code>
     * 或空字符串时，抛出此异常。
     */
    public static String getTagRegex(String tagName, boolean hasEndTag) {
        if (StringUtils.isNullOrEmpty(tagName))
            throw new IllegalArgumentException(Resources.getMessage(
                    Resources.UTIL_ERROR_EMPTY_NAME, "tagName"));
        tagName = tagName.trim().toUpperCase();
        if (tagRegexCaches.containsKey(tagName)) {
            return tagRegexCaches.get(tagName);
        } else {
            StringBuffer buffer = new StringBuffer();
            buffer.append("(?id)<").append(tagName).append("\\s+(.*?)\\s*");
            if(hasEndTag)
                buffer.append(">\\s*(.*?)\\s*</").append(tagName).append(">");
            else
                buffer.append("/?>");
            if(log.isDebugEnabled())
                log.debug(tagName + " Regex : " + buffer.toString());
            tagRegexCaches.put(tagName, buffer.toString());
            return tagRegexCaches.get(tagName);
        }
    }

    /**
     * 获取用于查找给定属性名称的 <code>HTML</code> 元素标签属性的正则表达式。
     * 
     * @param attrName 给定的标签属性名称(忽略大小写)。
     * @return 查找标签属性的正则表达式。
     * @throws IllegalArgumentException 若指定的标签属性名称 <tt>attrName</tt> 为 <code>NULL</code>
     * 或空字符串时，抛出此异常。
     */
    public static String getAttrRegex(String attrName) {
        if (StringUtils.isNullOrEmpty(attrName))
            throw new IllegalArgumentException(Resources.getMessage(
                    Resources.UTIL_ERROR_EMPTY_NAME, "attrName"));
        attrName = attrName.trim().toUpperCase();
        if (attrRegexCaches.containsKey(attrName)) {
            return attrRegexCaches.get(attrName);
        } else {
            StringBuffer buffer = new StringBuffer();
            buffer.append("(?ix)\\b").append(attrName).append("\\s*=\\s*");
            buffer.append("(?:\"([^\"]*)\"|'([^']*)'|([^'\">\\s]+))");
            if(log.isDebugEnabled())
                log.debug(attrName + " Regex : " + buffer.toString());
            attrRegexCaches.put(attrName, buffer.toString());
            return attrRegexCaches.get(attrName);
        }
    }
    
    /**
     * 创建指定网络路径的 <code>URL</code> 实例。
     * 
     * @param path 网络路径。
     * @return 指定网络路径的 <code>URL</code> 实例。
     */
    public static URL createURL(String path) {
        boolean isPath = getFindURLPattern().matcher(path).find();
        if(isPath) {
            try {
                return new URL(path);
            } catch(MalformedURLException e) {
                log.error(Resources.getMessage(Resources.UTIL_ERROR_URLPATH, "path"), e);
                return null;
            }
        }
        return null;
    }
}
